﻿using System;
using System.Diagnostics;
using System.IO;
using System.Management;
using System.Runtime.InteropServices;
using System.Text;

namespace PowerPlan
{
    /// <summary>
    /// 计算机
    /// </summary>
    public class Computer
    {

        // 用于获得CPU信息
        private static PerformanceCounter[] counters;

        static Computer()
        {
            // 初始化计数器
            counters = new PerformanceCounter[System.Environment.ProcessorCount];
            for (int i = 0; i < counters.Length; i++)
            {
                counters[i] = new PerformanceCounter("Processor", "% Processor Time", i.ToString());
                counters[i].NextValue(); // 这里是为了获得CPU占用率的值
            }
        }

        #region 执行CMD命令
        private static string CmdPath = @"C:\Windows\System32\cmd.exe";
        /// <summary>
        /// 执行cmd命令 返回cmd窗口显示的信息
        /// 多命令请使用批处理命令连接符：
        /// <![CDATA[
        /// &:同时执行两个命令
        /// |:将上一个命令的输出,作为下一个命令的输入
        /// &&：当&&前的命令成功时,才执行&&后的命令
        /// ||：当||前的命令失败时,才执行||后的命令]]>
        /// </summary>
        /// <param name="cmd">执行的命令</param>
        public static string RunCmd(string cmd)
        {
            cmd = cmd.Trim().TrimEnd('&') + "&exit";//说明：不管命令是否成功均执行exit命令，否则当调用ReadToEnd()方法时，会处于假死状态
            using (Process p = new Process())
            {
                p.StartInfo.FileName = CmdPath;
                p.StartInfo.UseShellExecute = false;        //是否使用操作系统shell启动
                p.StartInfo.RedirectStandardInput = true;   //接受来自调用程序的输入信息
                p.StartInfo.RedirectStandardOutput = true;  //由调用程序获取输出信息
                p.StartInfo.RedirectStandardError = true;   //重定向标准错误输出
                p.StartInfo.CreateNoWindow = true;          //不显示程序窗口
                p.Start();//启动程序

                //向cmd窗口写入命令
                p.StandardInput.WriteLine(cmd);
                p.StandardInput.AutoFlush = true;

                //获取cmd窗口的输出信息
                string output = p.StandardOutput.ReadToEnd();
                p.WaitForExit();//等待程序执行完退出进程
                p.Close();

                return output;
            }
        }
        #endregion

        #region 键鼠空闲时间
        /// <summary>
        /// 空闲时间
        /// </summary>
        /// <returns>键鼠空闲时间，单位秒</returns>
        public static long GetIdleTimeSeconds()
        {
            LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
            lastInputInfo.cbSize = Marshal.SizeOf(lastInputInfo);
            if (!GetLastInputInfo(ref lastInputInfo)) return 0;
            return (Environment.TickCount - (long)lastInputInfo.dwTime) / 1000;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct LASTINPUTINFO
        {
            [MarshalAs(UnmanagedType.U4)]
            public int cbSize;
            [MarshalAs(UnmanagedType.U4)]
            public uint dwTime;
        }
        /// <summary>
        /// 调用windows API获取鼠标键盘空闲时间
        /// </summary>
        /// <param name="plii"></param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
        #endregion

        #region CPU使用率
        /// <summary>
        /// 获取所有核心的CPU的占用率的值
        /// </summary>
        /// <returns></returns>
        public static double[] GetCPUUsage()
        {
            double[] info = new double[counters.Length];
            for (int i = 0; i < counters.Length; i++)
                info[i] = counters[i].NextValue();

            return info;
        }

        /// <summary>
        /// 获取CPU总使用率
        /// </summary>
        /// <returns></returns>
        public static double GetCPUTotalUsage()
        {
            double[] cpuUsages = GetCPUUsage();
            double usage = 0d;
            foreach(double cpuUsage in cpuUsages)
            {
                usage += cpuUsage;
            }
            usage = usage / cpuUsages.Length;
            return usage;
        }
        #endregion

        #region CPU信息
        public static string GetCPUInfo()
        {
            var cpu = new StringBuilder();
            var moc = new ManagementClass("Win32_Processor").GetInstances();
            foreach (var mo in moc)
            {
                foreach (var item in mo.Properties)
                {
                    cpu.Append($"{item.Name}:{item.Value}\r\n");
                }
            }
            return cpu.ToString();
        }
        #endregion

        #region App.ini文件操作
        /// <summary>
        /// AppData目录
        /// </summary>
        private static string AppData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
        /// <summary>
        /// INI文件地址
        /// </summary>
        private static string AppIniPath;

        /// <summary>
        /// Win32API：写入配置
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <param name="val"></param>
        /// <param name="filePath"></param>
        /// <returns></returns>
        [DllImport("kernel32")] //返回0表示失败，非0为成功
        private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
        /// <summary>
        /// Win32API：读取配置
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <param name="def"></param>
        /// <param name="retVal"></param>
        /// <param name="size"></param>
        /// <param name="filePath"></param>
        /// <returns></returns>
        [DllImport("kernel32")] //返回取得字符串缓冲区的长度
        private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);

        /// <summary>
        /// 设置INI
        /// </summary>
        /// <param name="section">缓冲区</param>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        public static void WriteValue(string section, string key, object value)
        {
            try
            {
                WritePrivateProfileString(section, key, value.ToString(), GetProcessIniPath());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        /// <summary>
        /// 读取INI
        /// </summary>
        /// <param name="section">缓冲区</param>
        /// <param name="key">键</param>
        /// <returns></returns>
        public static string ReadValue(string section, string key, string defaultValue)
        {
            try
            {
                StringBuilder temp = new StringBuilder(255);
                int i = GetPrivateProfileString(section, key, "", temp, 255, GetProcessIniPath());

                string value = temp.ToString();
                if (String.IsNullOrWhiteSpace(value))
                    return defaultValue;
                return value;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return defaultValue;
            }
        }

        /// <summary>
        /// 获取INI文件路径
        /// </summary>
        /// <returns></returns>
        private static string GetProcessIniPath()
        {
            try
            {
                if (String.IsNullOrWhiteSpace(AppIniPath))
                {
                    string ProcessName = Process.GetCurrentProcess().ProcessName;
                    AppIniPath = string.Format("{0}\\{1}\\{2}.ini", AppData, ProcessName, ProcessName);
                    Console.WriteLine("AppIniPath=" + AppIniPath);
                    DirectoryInfo dir = new DirectoryInfo(AppData + "\\" + ProcessName);
                    if (!dir.Exists)
                        dir.Create();
                    FileInfo ini = new FileInfo(AppIniPath);
                    if (!ini.Exists) 
                        ini.Create();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return AppIniPath;
        }
        #endregion
    }
}
